import { Space, Divider, Tooltip } from 'antd'
import { useEffect, useState, forwardRef, useImperativeHandle, useContext } from 'react'
import { default as Button } from '../components/ToolbarButton'
import { AlertOutlined } from '@ant-design/icons'
import ProcessEditorContext from '../context'
import FLOWABLE from "../FLOWABLE";



const useUndoRedo = (editorManager) => {

  const [undoStack, setUndoStack] = useState([])
  const [redoStack, setRedoStack] = useState([])

  const bindClearUndoRedo = () => {
    setUndoStack([])
    setRedoStack([])
  }

  useEffect(() => {
    FLOWABLE.eventBus.addListener(FLOWABLE.eventBus.EVENT_TYPE_UNDO_REDO_RESET, bindClearUndoRedo)
    return () => {
      FLOWABLE.eventBus.removeListener(FLOWABLE.eventBus.EVENT_TYPE_UNDO_REDO_RESET, bindClearUndoRedo)
    }
  }, [])

  const handleUndo = () => {
    const _undoStack = Object.assign(undoStack);
    var lastCommands = undoStack.pop()
    setUndoStack(_undoStack)
    // var lastCommands = undoStack[undoStack.length - 1];
    // setUndoStack(undoStack.filter((el, i) => i !== undoStack.length - 1))
    // debugger
    if (lastCommands) {
      setRedoStack(redoStack.concat([lastCommands]))
      for (var i = lastCommands.length - 1; i >= 0; --i) {
        lastCommands[i].rollback();
      }
      editorManager.handleEvents({
        type: ORYX.CONFIG.EVENT_UNDO_ROLLBACK,
        commands: lastCommands
      });
      editorManager.getCanvas().update();
      editorManager.updateSelection();
    }
  }

  const handleRedo = () => {
    const _redoStack = Object.assign(redoStack);
    var lastCommands = redoStack.pop()
    setRedoStack(_redoStack)
    // var lastCommands = redoStack[redoStack.length - 1];
    // setRedoStack(redoStack.filter((el, i) => i !== redoStack.length - 1))

    if (lastCommands) {
      setUndoStack(undoStack.concat([lastCommands]))
      lastCommands.each(function (command) {
        command.execute();
      });
      editorManager.handleEvents({
        type: ORYX.CONFIG.EVENT_UNDO_EXECUTE,
        commands: lastCommands
      });
      editorManager.getCanvas().update();
      editorManager.updateSelection();
    }
  }

  return {
    undoStack,
    setUndoStack,
    redoStack,
    setRedoStack,
    handleUndo,
    handleRedo
  }
}

const Toolbar = ({ }, ref) => {

  const {
    leftSlot,
    rightSlot,
    editorManager
  } = useContext(ProcessEditorContext)

  const {
    undoStack,
    setUndoStack,
    redoStack,
    setRedoStack,
    handleUndo,
    handleRedo
  } = useUndoRedo(editorManager)

  useImperativeHandle(ref, () => {
    return {
      delete() {
        handleAction('delete')
      }
    }
  })

  const [oryxEditPlugin, setOryxEditPlugin] = useState(null)
  const [oryxDockerPlugin, setOryxDockerPlugin] = useState(null)
  const [oryxArrangmentPlugin, setOryxArrangmentPlugin] = useState(null)
  const [oryxViewPlugin, setOryxViewPlugin] = useState(null)


  const getOryxEditPlugin = () => {
    if (!oryxEditPlugin) {
      const _oryxEditPlugin = new ORYX.Plugins.Edit(editorManager.getEditor());
      setOryxEditPlugin(_oryxEditPlugin)
      return _oryxEditPlugin;
    } else {
      return oryxEditPlugin
    }
  }

  const getOryxViewPlugin = () => {
    if (!oryxViewPlugin) {
      const _oryxViewPlugin = new ORYX.Plugins.View(editorManager.getEditor())
      setOryxViewPlugin(_oryxViewPlugin)
      return _oryxViewPlugin;
    } else {
      return oryxViewPlugin
    }
  }

  const getOryxDockerPlugin = () => {
    if (!oryxDockerPlugin) {
      const _oryxDockerPlugin = new ORYX.Plugins.AddDocker(editorManager.getEditor());
      setOryxDockerPlugin(_oryxDockerPlugin)
      return _oryxDockerPlugin;
    } else {
      return oryxDockerPlugin
    }
  }

  const getOryxArrangmentPlugin = () => {
    if (!oryxArrangmentPlugin) {
      const _oryxArrangmentPlugin = new ORYX.Plugins.Arrangement(editorManager.getEditor());
      setOryxArrangmentPlugin(_oryxArrangmentPlugin)
      return _oryxArrangmentPlugin;
    } else {
      return oryxArrangmentPlugin
    }
  }

  const handleAction = (type) => {
    switch (type) {

      case 'undo':
        handleUndo()
        break
      case 'redo':
        handleRedo()
        break

      case 'cut':
        getOryxEditPlugin().editCut()
        setPasteDisabled(true)
        setPasteDisabled(false)
        break;
      case 'copy':
        getOryxEditPlugin().editCopy()
        setPasteDisabled(true)
        setPasteDisabled(false)
        break;
      case 'paste':
        getOryxEditPlugin().editPaste()
        break;
      case 'delete':
        getOryxEditPlugin().editDelete()
        break;

      case 'zoomIn':
        getOryxViewPlugin().zoom([1.0 + ORYX.CONFIG.ZOOM_OFFSET])
        break;
      case 'zoomOut':
        getOryxViewPlugin().zoom([1.0 - ORYX.CONFIG.ZOOM_OFFSET]);
        break;
      case 'zoomActual':
        getOryxViewPlugin().setAFixZoomLevel(1);
        break;
      case 'zoomFit':
        getOryxViewPlugin().zoomFitToModel();
        break;

      case 'alignVertical':
        getOryxArrangmentPlugin().alignShapes([ORYX.CONFIG.EDITOR_ALIGN_CENTER])
        break;
      case 'alignHorizontal':
        getOryxArrangmentPlugin().alignShapes([ORYX.CONFIG.EDITOR_ALIGN_MIDDLE]);
        break;
      case 'sameSize':
        getOryxArrangmentPlugin().alignShapes([ORYX.CONFIG.EDITOR_ALIGN_SIZE]);
        break;

      case 'addBendpoint':
        var dockerPlugin = getOryxDockerPlugin();
        var enableAdd = !dockerPlugin.enabledAdd();
        dockerPlugin.setEnableAdd(enableAdd);
        if (enableAdd) {
          dockerPlugin.setEnableRemove(false);
          document.body.style.cursor = 'pointer';
        } else {
          document.body.style.cursor = 'default';
        }
        break
      case 'removeBendPoint':
        var dockerPlugin = getOryxDockerPlugin();
        var enableRemove = !dockerPlugin.enabledRemove();
        dockerPlugin.setEnableRemove(enableRemove);
        if (enableRemove) {
          dockerPlugin.setEnableAdd(false);
          document.body.style.cursor = 'pointer';
        } else {
          document.body.style.cursor = 'default';
        }
        break
    }
  }

  const [elements, setElements] = useState([])
  const [pasteDisabled, setPasteDisabled] = useState(true)

  useEffect(() => {
    if (window.Mousetrap !== undefined) {
      Mousetrap.bind('mod+v', function (e) {
        handleAction('paste')
        return false;
      });
    }
    return () => {
      if (window.Mousetrap !== undefined) {
        Mousetrap.unbind('mod+v', function (e) {
          handleAction('paste')
          return false;
        });
      }
    }
  }, [pasteDisabled])

  useEffect(() => {
    if (window.Mousetrap !== undefined) {
      Mousetrap.bind('mod+z', (e) => {
        handleAction('undo')
        return false;
      });
      Mousetrap.bind('mod+y', (e) => {
        handleAction('redo')
        return false;
      });
    }
    return () => {
      if (window.Mousetrap !== undefined) {
        Mousetrap.unbind('mod+z', (e) => {
          handleAction('undo')
          return false;
        });
        Mousetrap.unbind('mod+y', (e) => {
          handleAction('redo')
          return false;
        });
      }
    }
  }, [undoStack, redoStack])

  useEffect(() => {
    if (editorManager) {
      editorManager.registerOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED, function (evt) {
        setElements(evt.elements)
      });

      editorManager.registerOnEvent(ORYX.CONFIG.EVENT_EXECUTE_COMMANDS, function (evt) {
        if (!evt.commands) { return; }
        // const _undoStack = Object.assign(undoStack)
        // _undoStack.push(evt.commands)
        // setUndoStack(_undoStack)
        setUndoStack((_undoStack) => {
          return _undoStack.concat([evt.commands])
        })

        setRedoStack([])
        // Update
        editorManager.getCanvas().update();
        editorManager.updateSelection();
      });

      if (Mousetrap) {

        Mousetrap.bind('mod+c', function (e) {
          handleAction('copy')
          return false;
        });

        Mousetrap.bind('mod+x', function (e) {
          handleAction('cut')
          return false;
        });


        Mousetrap.bind(['del'], function (e) {
          handleAction('delete')
          return false;
        });
      }
    }
  }, [editorManager])

  return <div className="p-d-toolbar">
    <div>
      {leftSlot}
    </div>
    <Space>
      <Button
        onClick={() => { handleAction('cut') }}
        disabled={elements.length === 0}
        title="剪切 (在业务流程中选择一个或多个元素)"
      >
        <i className="editor-icon editor-icon-cut"></i>
      </Button>
      <Button
        onClick={() => { handleAction('copy') }}
        disabled={elements.length === 0}
        title="拷贝 (在业务流程中选择一个或多个元素)"
      >
        <i className="editor-icon editor-icon-copy"></i>
      </Button>
      <Button
        onClick={() => { handleAction('paste') }}
        disabled={pasteDisabled}
        title="粘贴"
      >
        <i className="editor-icon editor-icon-paste"></i>
      </Button>
      <Button
        onClick={() => { handleAction('delete') }}
        disabled={elements.length === 0}
        title="删除选定元素"
      >
        <i className="editor-icon editor-icon-delete"></i>
      </Button>

      <Divider type="vertical"></Divider>

      <Button
        disabled={undoStack.length === 0}
        onClick={() => { handleAction('undo') }}
        title="重做"
      >
        <i className="editor-icon editor-icon-undo"></i>
      </Button>
      <Button
        disabled={redoStack.length === 0}
        onClick={() => { handleAction('redo') }}
        title="撤消"
      >
        <i className="editor-icon editor-icon-redo"></i>
      </Button>

      <Divider type="vertical"></Divider>

      <Button
        onClick={() => { handleAction('alignVertical') }}
        disabled={elements.length < 2}
        title="垂直对齐"
      >
        <i className="editor-icon editor-icon-align-vertical"></i>
      </Button>
      <Button
        onClick={() => { handleAction('alignHorizontal') }}
        disabled={elements.length < 2}
        title="水平对齐"
      >
        <i className="editor-icon editor-icon-align-horizontal"></i>
      </Button>
      <Button
        onClick={() => { handleAction('sameSize') }}
        disabled={elements.length < 2}
        title="相同大小"
      >
        <i className="editor-icon editor-icon-same-size"></i>
      </Button>

      <Divider type="vertical"></Divider>

      <Button onClick={() => { handleAction('zoomIn') }} title="放大">
        <i className="editor-icon editor-icon-zoom-in"></i>
      </Button>
      <Button onClick={() => { handleAction('zoomOut') }} title="缩小">
        <i className="editor-icon editor-icon-zoom-out"></i>
      </Button>
      <Button onClick={() => { handleAction('zoomActual') }} title="缩放到实际尺寸">
        <i className="editor-icon editor-icon-zoom-actual"></i>
      </Button>
      <Button onClick={() => { handleAction('zoomFit') }} title="缩放到适当大小">
        <i className="editor-icon editor-icon-zoom-fit"></i>
      </Button>

      <Divider type="vertical"></Divider>

      <Button onClick={() => { handleAction('addBendpoint') }} title="向选定的连线添加弯曲点">
        <i id="add-bendpoint-button" className="editor-icon editor-icon-bendpoint-add"></i>
      </Button>
      <Button onClick={() => { handleAction('removeBendPoint') }} title="向选定的连线移除弯曲点">
        <i id="remove-bendpoint-button" className="editor-icon editor-icon-bendpoint-remove"></i>
      </Button>
    </Space>
    <div>
      {rightSlot}
    </div>
  </div>
}

export default forwardRef(Toolbar)